package com.core.cloudbusiness.system.trace.controller;

import com.core.cloudbusiness.system.trace.service.TraceQueryService;
import com.core.cloudcommon.CommonResult;
import com.core.cloudcommon.trace.TraceLogger;
import com.core.cloudcommon.trace.TraceResultCode;
import com.core.cloudcommon.trace.Traceable;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.List;
import java.util.Map;

/**
 * @author =====Lqj=====
 * @className TraceQueryController
 * @description 链路追踪查询控制器
 * @create 2024/12/17 10:30
 **/
@Slf4j
@RestController
@RequestMapping("/api/trace")
public class TraceQueryController {

    @Autowired
    private TraceQueryService traceQueryService;

    /**
     * 根据链路ID查询所有相关日志
     *
     * @param traceId 链路ID
     * @return 日志列表
     */
    @GetMapping("/logs/{traceId}")
    @Traceable(operation = "查询链路日志", description = "根据链路ID查询所有相关日志")
    public CommonResult<Object> queryLogsByTraceId(@PathVariable String traceId) {
        // 参数验证
        if (traceId == null || traceId.trim().isEmpty()) {
            return CommonResult.error(TraceResultCode.TRACE_ID_NULL.getCode(),
                                    TraceResultCode.TRACE_ID_NULL.getMessage());
        }

        // 链路ID格式验证（32位十六进制字符串）
        if (!traceId.matches("^[a-f0-9]{32}$")) {
            return CommonResult.error(TraceResultCode.TRACE_ID_INVALID.getCode(),
                                    TraceResultCode.TRACE_ID_INVALID.getMessage());
        }

        TraceLogger.business("查询链路日志", "查询链路ID: " + traceId, null);

        try {
            List<Map<String, Object>> logs = traceQueryService.queryLogsByTraceId(traceId);
            TraceLogger.business("查询链路日志", "查询完成", "找到 " + logs.size() + " 条日志");
            return CommonResult.OK(logs);
        } catch (Exception e) {
            TraceLogger.error("查询链路日志失败: {}", e.getMessage(), e);
            return CommonResult.error(TraceResultCode.TRACE_QUERY_FAILED.getCode(),
                                    TraceResultCode.TRACE_QUERY_FAILED.getMessage());
        }
    }

    /**
     * 根据链路ID查询链路信息
     *
     * @param traceId 链路ID
     * @return 链路信息
     */
    @GetMapping("/info/{traceId}")
    @Traceable(operation = "查询链路信息", description = "根据链路ID查询链路基本信息")
    public CommonResult<Object> queryTraceInfo(@PathVariable String traceId) {
        TraceLogger.business("查询链路信息", "查询链路ID: " + traceId, null);
        
        Map<String, Object> traceInfo = traceQueryService.queryTraceInfo(traceId);
        if (traceInfo == null) {
            TraceLogger.warn("链路信息不存在: {}", traceId);
            return CommonResult.error(TraceResultCode.TRACE_NOT_FOUND.getCode(),
                                    TraceResultCode.TRACE_NOT_FOUND.getMessage());
        }
        
        TraceLogger.business("查询链路信息", "查询完成", traceInfo);
        return CommonResult.OK(traceInfo);
    }

    /**
     * 根据链路ID查询业务操作记录
     * @param traceId 链路ID
     * @return 业务操作记录
     */
    @GetMapping("/business/{traceId}")
    @Traceable(operation = "查询业务操作", description = "根据链路ID查询业务操作记录")
    public CommonResult<List<Map<String, Object>>> queryBusinessOperations(@PathVariable String traceId) {
        List<Map<String, Object>> operations = traceQueryService.queryBusinessOperations(traceId);
        return CommonResult.OK(operations);
    }

    /**
     * 根据链路ID查询数据库操作记录
     * @param traceId 链路ID
     * @return 数据库操作记录
     */
    @GetMapping("/database/{traceId}")
    @Traceable(operation = "查询数据库操作", description = "根据链路ID查询数据库操作记录")
    public CommonResult<List<Map<String, Object>>> queryDatabaseOperations(@PathVariable String traceId) {
        List<Map<String, Object>> operations = traceQueryService.queryDatabaseOperations(traceId);
        return CommonResult.OK(operations);
    }

    /**
     * 根据链路ID查询外部接口调用记录
     * @param traceId 链路ID
     * @return 外部接口调用记录
     */
    @GetMapping("/external/{traceId}")
    @Traceable(operation = "查询外部调用", description = "根据链路ID查询外部接口调用记录")
    public CommonResult<List<Map<String, Object>>> queryExternalCalls(@PathVariable String traceId) {
        List<Map<String, Object>> calls = traceQueryService.queryExternalCalls(traceId);
        return CommonResult.OK(calls);
    }

    /**
     * 根据链路ID查询缓存操作记录
     * @param traceId 链路ID
     * @return 缓存操作记录
     */
    @GetMapping("/cache/{traceId}")
    @Traceable(operation = "查询缓存操作", description = "根据链路ID查询缓存操作记录")
    public CommonResult<List<Map<String, Object>>> queryCacheOperations(@PathVariable String traceId) {
        List<Map<String, Object>> operations = traceQueryService.queryCacheOperations(traceId);
        return CommonResult.OK(operations);
    }

    /**
     * 根据链路ID查询性能监控记录
     * @param traceId 链路ID
     * @return 性能监控记录
     */
    @GetMapping("/performance/{traceId}")
    @Traceable(operation = "查询性能记录", description = "根据链路ID查询性能监控记录")
    public CommonResult<List<Map<String, Object>>> queryPerformanceRecords(@PathVariable String traceId) {
        List<Map<String, Object>> records = traceQueryService.queryPerformanceRecords(traceId);
        return CommonResult.OK(records);
    }

    /**
     * 根据链路ID查询安全事件记录
     * @param traceId 链路ID
     * @return 安全事件记录
     */
    @GetMapping("/security/{traceId}")
    @Traceable(operation = "查询安全事件", description = "根据链路ID查询安全事件记录")
    public CommonResult<List<Map<String, Object>>> querySecurityEvents(@PathVariable String traceId) {
        List<Map<String, Object>> events = traceQueryService.querySecurityEvents(traceId);
        return CommonResult.OK(events);
    }

    /**
     * 根据链路ID查询完整的链路追踪报告
     *
     * @param traceId 链路ID
     * @return 完整的链路追踪报告
     */
    @GetMapping("/report/{traceId}")
    @Traceable(operation = "查询链路报告", description = "根据链路ID查询完整的链路追踪报告")
    public CommonResult<Object> queryFullTraceReport(@PathVariable String traceId) {
        TraceLogger.business("查询链路报告", "生成完整链路追踪报告: " + traceId, null);
        
        Map<String, Object> report = traceQueryService.queryFullTraceReport(traceId);
        if (report == null) {
            TraceLogger.warn("链路报告不存在: {}", traceId);
            return CommonResult.error(TraceResultCode.TRACE_REPORT_FAILED.getCode(),
                                    TraceResultCode.TRACE_REPORT_FAILED.getMessage());
        }
        
        TraceLogger.business("查询链路报告", "报告生成完成", report.get("statistics"));
        return CommonResult.OK(report);
    }

    /**
     * 根据用户ID查询链路ID列表
     * @param userId 用户ID
     * @param startTime 开始时间
     * @param endTime 结束时间
     * @return 链路ID列表
     */
    @GetMapping("/user/{userId}")
    @Traceable(operation = "查询用户链路", description = "根据用户ID查询链路ID列表")
    public CommonResult<List<String>> queryTraceIdsByUser(
            @PathVariable Long userId,
            @RequestParam(required = false) Long startTime,
            @RequestParam(required = false) Long endTime) {
        
        List<String> traceIds = traceQueryService.queryTraceIdsByUser(userId, startTime, endTime);
        return CommonResult.OK(traceIds);
    }

    /**
     * 根据请求URI查询链路ID列表
     * @param requestUri 请求URI
     * @param startTime 开始时间
     * @param endTime 结束时间
     * @return 链路ID列表
     */
    @GetMapping("/uri")
    @Traceable(operation = "查询URI链路", description = "根据请求URI查询链路ID列表")
    public CommonResult<List<String>> queryTraceIdsByUri(
            @RequestParam String requestUri,
            @RequestParam(required = false) Long startTime,
            @RequestParam(required = false) Long endTime) {
        
        List<String> traceIds = traceQueryService.queryTraceIdsByUri(requestUri, startTime, endTime);
        return CommonResult.OK(traceIds);
    }

    /**
     * 查询慢请求的链路ID列表
     * @param threshold 耗时阈值（毫秒）
     * @param startTime 开始时间
     * @param endTime 结束时间
     * @return 链路ID列表
     */
    @GetMapping("/slow")
    @Traceable(operation = "查询慢请求", description = "查询慢请求的链路ID列表")
    public CommonResult<List<String>> querySlowTraceIds(
            @RequestParam(defaultValue = "1000") Long threshold,
            @RequestParam(required = false) Long startTime,
            @RequestParam(required = false) Long endTime) {
        
        List<String> traceIds = traceQueryService.querySlowTraceIds(threshold, startTime, endTime);
        return CommonResult.OK(traceIds);
    }
}
